package com.systar.activity.ui;

import java.io.InputStream;
import java.util.ArrayList;

import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.ImageLoader;
import org.eclipse.swt.widgets.Display;

public abstract class AnimatedImage extends ImageDescriptor implements Runnable
{
	private static final int MILLISECONDS_OF_DELAY = 100;

	private ArrayList<ImageData> images;
	private int animationIndex;
	private volatile boolean animated;

	/**
	 * Animated image
	 * 
	 * @param fileStreams
	 *            the 1st image is the unactive image, the others are the active cycle
	 */
	public AnimatedImage(InputStream... fileStreams)
	{
		images = new ArrayList<ImageData>();
		animationIndex = 0;
		animated = false;

		for (InputStream imageStream : fileStreams)
		{
			ImageLoader loader = new ImageLoader();
			ImageData[] dataArray = loader.load(imageStream);
			if (dataArray != null)
				for (ImageData data : dataArray)
					images.add(data);
		}
	}

	public boolean isAnimated()
	{
		return animated;
	}

	public void setAnimated(boolean animated)
	{
		if (this.animated == animated)
			return;

		this.animated = animated;

		if (animated && (images.size() > 1))
		{
			animationIndex = 1;
			Display.getDefault().timerExec(MILLISECONDS_OF_DELAY, this);
		}
		else
		{
			animationIndex = 0;
		}
		fireImageChanged();
	}

	@Override
	public ImageData getImageData()
	{
		if (animationIndex < 0 || animationIndex >= images.size())
			return null;
		return images.get(animationIndex);
	}

	@Override
	public Image createImage()
	{
		return createImage(true);
	}

	public void dispose()
	{

	}

	@Override
	public synchronized void run()
	{
		if (!animated)
			return;

		//next
		animationIndex = (animationIndex + 1) % images.size();
		if (animationIndex == 0)
			animationIndex = 1;

		fireImageChanged();
		Display.getDefault().timerExec(MILLISECONDS_OF_DELAY, this);
	}

	public abstract void fireImageChanged();
}
